#include "main.h"

/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  map_mask
 *  Description:  
 *  Return: 0 OK, 1 nothing masked
 * =====================================================================================
 */
gint map_mask (GSList *root)
{
  gint full = 0;
  gint res_index = 0;
  GSList *list = root;

  while (list) {
    GSList *next = list->next;
    TreeAttr *tree = list->data;
    gint len = g_slist_length (tree->head);

    if (!tree->point) {
        // if set bit failed, full++
        if (map_set_pos_at (root, tree->index)) {
          full++;
        // if set bit success, erase all map before current index
        } else {
          map_erase_before (root, tree->index);
          return 0;
        }
    } else {
      // here we got the end the bit map, should init map again
      if (full == tree->index) {
        if (map_init (root))
          return 1;
        return 0;
      }
    }

    // restrict
    //if (len > 32)
    //  g_critical ("[map_mask]: length of the tree bigger than 32");

    list = next;
  }

  return 1;
}


/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  map_init
 *  Description:  
 *  Return: 0 success, 1 meet the end
 * =====================================================================================
 */
gint map_init (GSList *root)
{
  GSList *list = root;
  while (list) {
    GSList *next = list->next;
    TreeAttr *tree = list->data;

    if (!tree->point) {
      map_erase (root, tree->index);
    } else {
      if(map_set_pos_at (root, tree->index)) {
        if(next) {
          TreeAttr *tree2 = next->data;
          tree->point = 0;
          tree2->point = 1;
          //list = next;
          continue;
        } else
          return 1;
      }
    }

    //gchar buf [40];
    //g_debug ("[map_init]expr %d: map = %s", tree->index, itoa(tree->map, buf, 2));

    list = next;
  }

  return 0;
}


/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  map_erase
 *  Description:  
 *  Return: 0 success 1 failed and nothing set
 * =====================================================================================
 */
gint map_erase (GSList *root, gint index)
{
  TreeAttr *tree = g_slist_nth_data (root, index);
  gint len = g_slist_length (tree->head);

  tree->map = 1;

  if (len == 1)
    return 1;

  return 0;
}


/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  map_erase_before
 *  Description:  erease the map before index to 1
 * =====================================================================================
 */
void map_erase_before (GSList *root, gint index)
{
  GSList *list = root;
  while (list) {
    GSList *next = list->next;
    TreeAttr *tree = list->data;
    if (tree->index >= index)
      break;

    tree->map = 1;

    list = next;
  }
}


/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  map_get_pos_at
 *  Description:  
 * =====================================================================================
 */
gint map_get_pos_at (GSList *root, gint index)
{
  GSList *list = root;
  while (list) {
    GSList *next = list->next;
    TreeAttr *tree = list->data;

    // Traversing until index
    if (tree->index == index) {

      // Traversing until bit value == 0
      gint i = 0;
      while (1) {
        gint map2 = 1 << i;
        if (!(tree->map & map2)) {
        break;
      }
      i++;
    }

    i--;

    return i;
  }

    list = next;
  }
}


/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  map_set_pos_at
 *  Description:  set position bit at giving index
 *  Return: 0 success 1 failed
 * =====================================================================================
 */
gint map_set_pos_at (GSList *root, gint index)
{
  GSList *list = root;
  while (list) {
    GSList *next = list->next;
    TreeAttr *tree = list->data;

    // Traversing until index
    if (tree->index == index) {
      gint len = g_slist_length (tree->head);

      // Traversing until bit value == 0
      gint i = 0;
      while (1) {
        gint map2 = 1 << i;
        if (!(tree->map & map2)) {
          break;
        }
        i++;
      }

      i--;

      if (i + 1 == len) {
        // end
        return 1;
      } else {
        // set bit
        gint map2 = 1 << (i + 1);
        tree->map |= map2;
        return 0;
      }
    }

    list = next;
  }
}
